import Ux from "ux";
// -------------------------------------- 新旧版本分界 -------------------------------
const kvH = (reference, param = {}) => {
    const {webValue: {h = {}}} = param;
    const {data} = reference.props;
    const dataArray = Ux.elementFlip(data);
    const {mapping = {}, value = {}} = h;
    const kv = Ux.toKV(mapping);
    return {
        source: dataArray,  // ui 数据源
        kv,                 // from = to
        value,              // 初始化数据
    }
}
/*
 * - H, rows
 * - V, projection
 * - Q, criteria
 */
const HVQ = {
    /*
     * H - rows, S - single
     * [k,v], [k,v], [k,v], [k,v], [k,v]
     * - value[v] = [v1,v2,v3,...]
     * - dataArray 使用 v 过滤提取元素
     * - map 计算使用 k 执行，得到最终值
     */
    aclInHS: (reference, param = {}) => {
        const {
            source = [],
            kv, value,
        } = kvH(reference, param);

        const initial = Ux.isArray(value[kv.to]) ? value[kv.to] : [];
        const keys = source
            .filter(item => initial.includes(item[kv.to]))
            .map(item => item[kv.from]);
        return new Set(keys);
    },
    // rows -> submit
    aclOutHS: (reference, param = {}) => {
        const {
            source = [],
            kv,
        } = kvH(reference, param);
        const {webSelected = []} = param;
        // 构造 rows
        const toValue = source
            .filter(item => webSelected.includes(item[kv.from]))
            .map(item => item[kv.to]);
        const request = {};
        request[kv.to] = toValue;
        return {
            rows: request
        }
    }
}
/*
 * 「RBAC」
 * 新版本权限路由专用，用于执行权限路由路径
 * 权限路由进入权限设置主界面
 * params的数据结构
 * {
 *    "key": "实体Key，角色或用户ID",
 *    "view": "视图类型，角色 = ROLE，用户 = USER",
 *    "admit": "特权标记（角色才拥有，是否拥有超级权限）"
 * }
 */
const aclRoute = (reference, params = {}) => {
    /* 跳转到管理界面 */
    const {
        key,
        view,
        data,
    } = params;
    const normalized = {};
    if (key && view) {
        /* 全部改成内置参数 */
        normalized._key = key;
        normalized._view = view;
        normalized._data = data;
        const {$router} = reference.props;
        normalized.target = $router.path();   // 追加 target 参数
        Ux.toRoute(reference, "/rbac/authority", normalized);
    } else {
        console.error("调用错误，必须传入 key 和 view 参数！");
    }
}
// ExAuthority usage
const aclRegion = async (request = {}, state = {}) => {
    // 提取视图类型
    const {type, key} = request;
    // 提取区域
    const $regions = await Ux.ajaxGet("/api/authority/region/:type", {
        type,
    });
    state.$regions = $regions;
    // 区域值（提取 resource = value）
    if (0 < $regions.length) {
        const region = $regions[0];
        state.$initial = await Ux.ajaxPost("/api/authority/region-v/:key", {
            key,
            $body: region.datum,
        })
    } else {
        state.$initial = {}
    }
    return state;
}
const aclAdmit = (reference, region = {}) => {
    const inherit = {};
    const {$inited = {}} = reference.props;
    inherit.$owner = $inited.data ? $inited.data : {};
    inherit.$region = region;

    const $initial = {};
    $initial.ownerType = $inited.type;
    $initial.owner = $inited.key;

    const {
        config = {}, group,
        datum, data
    } = region;
    const {
        webBind,
        webView = {},
    } = config;

    /* name / position */
    Object.assign($initial, webView);

    if (webBind) {
        const {$initial = {}} = reference.state;
        inherit.$inited = $initial[webBind];
    }
    inherit.$initial = $initial;

    const {$loading = false} = reference.state;
    inherit.$loading = $loading;
    inherit.data = data;
    inherit.config = {
        ...config,      // webBind is required for children updating
        group,
        datum,
    }
    return inherit;
}
const aclIn = (reference) => {
    const {config = {}, $inited = {}} = reference.props;
    const {webData = {}} = config;
    const {
        initializer
    } = webData;
    if (!initializer) {
        console.warn("[ACL] initializer 未配置", initializer)
        return new Set();
    }
    const executor = HVQ[initializer];
    if (Ux.isFunction(executor)) {
        const params = {};
        params.webValue = $inited;
        params.webData = webData;
        /*
         * {
         *     "webValue": "xxx",
         *     "webData": {}
         * }
         * 由于 reference.props 中已经存在 data, config,
         * 为了区分，就使用 webValue, webData
         */
        return executor(reference, params);
    } else {
        console.warn("[ACL] initializer 不存在", initializer)
        return new Set();
    }
}
const aclOut = (reference, $keySet) => {
    const {config = {}, $inited = {}} = reference.props;
    const {webData = {}, webBind} = config;
    const {
        requester
    } = webData;
    if (!requester) {
        console.warn("[ACL] requester 未配置", requester)
        return new Set();
    }
    const executor = HVQ[requester];
    if (Ux.isFunction(executor)) {
        const params = {};
        params.webValue = $inited;
        params.webSelected = Array.from($keySet);
        params.webData = webData;
        /*
         * {
         *     "webValue": "xxx",
         *     "webData": {}
         * }
         * 由于 reference.props 中已经存在 data, config,
         * 为了区分，就使用 webValue, webData
         */
        const viewData = executor(reference, params);
        const {$initial = {}} = reference.props;
        const request = Ux.clone($initial);
        request.resource = {};
        request.resource[webBind] = viewData;
        return request;
    } else {
        console.warn("[ACL] requester 不存在", requester)
        return new Set();
    }
}
/*
 * viewData结构
 * {
 *     "rows": {},
 *     "projection": [],
 *     "criteria": {}
 * }
 */
export default {
    // 新接口，用于新的权限管理
    aclRoute,               // 权限路由
    aclRegion,              // 权限区域管理
    /*
     * {
     *      ...yoAmbient,
     *      $inited:     The value selected,
     *      data:        UI Data,
     *      config:     {
     *           ...config,
     *           datum,
     *           group
     *      }
     * }
     */
    aclAdmit,       // 权限区域内容
    // ------------- 数据处理
    aclIn,        // 构造 $keySet
    aclOut,      // 构造请求数据
}